package com.zndroid.utils.impl;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * 通用时间类
 *
 * @author lzy
 */
@SuppressWarnings("unused")
public class TimeUtil {
	/**系统计时开始时间
	 */
	private final int[] SYSTEM_START_DATE = {1970, 0, 1, 0, 0, 0};

	private final int LEVEL_YEAR = 0;
	private final int LEVEL_MONTH = 1;
	private final int LEVEL_DAY = 2;
	private final int LEVEL_HOUR = 3;
	private final int LEVEL_MINUTE = 4;
	private final int LEVEL_SECOND = 5;
	private final int[] LEVELS = {
		LEVEL_YEAR,
		LEVEL_MONTH,
		LEVEL_DAY,
		LEVEL_HOUR,
		LEVEL_MINUTE,
		LEVEL_SECOND,
	};

	private final String NAME_YEAR = "年";
	private final String NAME_MONTH = "月";
	private final String NAME_DAY = "日";
	private final String NAME_HOUR = "时";
	private final String NAME_MINUTE = "分";
	private final String NAME_SECOND = "秒";
	private final String[] LEVEL_NAMES = {
		NAME_YEAR,
		NAME_MONTH,
		NAME_DAY,
		NAME_HOUR,
		NAME_MINUTE,
		NAME_SECOND,
	};

	/**
	 * @param level int
	 * @return true or false
	 */
	private boolean isContainLevel(int level) {
		for (int existLevel : LEVELS) {
			if (level == existLevel) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @param level int
	 * @return name
	 */
	private String getNameByLevel(int level) {
		return isContainLevel(level) ? LEVEL_NAMES[level - LEVEL_YEAR] : "";
	}

	private static class Day {
		private static final String NAME_THE_DAY_BEFORE_YESTERDAY = "前天";
		private static final String NAME_YESTERDAY = "昨天";
		private static final String NAME_TODAY = "今天";
		private static final String NAME_TOMORROW = "明天";
		private static final String NAME_THE_DAY_AFTER_TOMORROW = "后天";


		private static final int TYPE_SUNDAY = 0;
		private static final int TYPE_MONDAY = 1;
		private static final int TYPE_TUESDAY = 2;
		private static final int TYPE_WEDNESDAY = 3;
		private static final int TYPE_THURSDAY = 4;
		private static final int TYPE_FRIDAY = 5;
		private static final int TYPE_SATURDAY = 6;
		private static final int[] DAY_OF_WEEK_TYPES = {
			TYPE_SUNDAY,
			TYPE_MONDAY,
			TYPE_TUESDAY,
			TYPE_WEDNESDAY,
			TYPE_THURSDAY,
			TYPE_FRIDAY,
			TYPE_SATURDAY,
		};

		private static final String NAME_SUNDAY = "日";
		private static final String NAME_MONDAY = "一";
		private static final String NAME_TUESDAY = "二";
		private static final String NAME_WEDNESDAY = "三";
		private static final String NAME_THURSDAY = "四";
		private static final String NAME_FRIDAY = "五";
		private static final String NAME_SATURDAY = "六";
		private static final String[] DAY_OF_WEEK_NAMES = {
			NAME_SUNDAY,
			NAME_MONDAY,
			NAME_TUESDAY,
			NAME_WEDNESDAY,
			NAME_THURSDAY,
			NAME_FRIDAY,
			NAME_SATURDAY,
		};

		private static boolean isContainType(int type) {
			for (int existType : DAY_OF_WEEK_TYPES) {
				if (type == existType) {
					return true;
				}
			}
			return false;
		}

        private static String getDayNameOfWeek(int type) {
			return isContainType(type) ? DAY_OF_WEEK_NAMES[type - TYPE_SUNDAY] : "";
		}	

	}

	private final int YEAR = 0;
	private final int MONTH = 1;
	private final int DAY_OF_MONTH = 2;
	private final int HOUR_OF_DAY = 3;
	private final int MINUTE = 4;
	private final int SECOND = 5;

	private final int[] MIN_TIME_DETAILS = {0, 0, 0};
	private final int[] MAX_TIME_DETAILS = {23, 59, 59};


	/**
     * 闰年？
     * @param year year
     * @return true or false
     * */
	public boolean isLeapYear(int year) {
		return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
	}

	/**
     * 秒转换为‘时:分:秒’格式
     * @param s second
     * @return format string like ‘00:12:55’
     * */
    public String second2HMS(int s) {
        String result;
        int hour = s / 3600;
        int mint = (s % 3600) / 60;
        int sed = s % 60;
        String hourStr = String.valueOf(hour);
        if (hour < 10) {
            hourStr = "0" + hourStr;
        }
        String mintStr = String.valueOf(mint);
        if (mint < 10) {
            mintStr = "0" + mintStr;
        }
        String sedStr = String.valueOf(sed);
        if (sed < 10) {
            sedStr = "0" + sedStr;
        }
        result = hourStr + ":" + mintStr + ":" + sedStr;
        return result;
    }

    /**
     * the current time
     * @return long - in milliseconds
     * */
    public long getCurrentTime() {
        return System.currentTimeMillis();
    }

    /**
     * 获取当前时间, 默认格式：‘hh:mm:ss’
     * @return string
     */
    public String getTime() {
        return getTime(new Date());
    }

	/**
     * 获取时间, 默认格式：‘hh:mm:ss’
	 * @param date Date
	 * @return string
	 */
	public String getTime(Date date) {
		return SimpleDateFormat.getTimeInstance().format(date);
    }

	/**
     * 获取时间, 默认格式：‘hh:mm:ss’
	 * @param date long
	 * @return string
	 */
	public String getTime(long date) {
		return getTime(new Date(date));
	}

    /**
     * 获取日期
     * @return string
     * */
    public String getDate() {
        return SimpleDateFormat.getDateInstance().format(new Date());
    }

    /**
     * 获取日期
     * @param date date
     * @return string
     * */
    public String getDate(Date date) {
        return SimpleDateFormat.getDateInstance().format(date);
    }

    /**
     * 获取日期
     * @param date long
     * @return string
     * */
    public String getDate(long date) {
        return SimpleDateFormat.getDateInstance().format(new Date(date));
    }

    /**
     * 指定格式化时间
     * @param date date
     * @param format formatString like ‘yyyyMMddHHmmss’
     * @return string
     */
    public String getFormatDateTime(Date date, String format) {
        return new SimpleDateFormat(format, Locale.getDefault()).format(date);
    }

    /**
     * 指定格式化时间
     * @param date long
     * @return string
     */
    public String getFormatDateTime(long date, String format) {
        return new SimpleDateFormat(format, Locale.getDefault()).format(new Date(date));
    }

    /**
     * 毫秒转化‘天时分秒’
     *
     * @param ms long
     * @return format time
     */
    public String formatTime(long ms) {
        return formatTime(ms, true);
    }

    public String formatTime(long ms, boolean china) {
        int ss = 1000;
        int mi = ss * 60;
        int hh = mi * 60;
        int dd = hh * 24;

        long day = ms / dd;
        long hour = (ms - day * dd) / hh;
        long minute = (ms - day * dd - hour * hh) / mi;
        long second = (ms - day * dd - hour * hh - minute * mi) / ss;

        StringBuilder sb = new StringBuilder();
        if (day > 0) {
            sb.append(day).append(china ? "天" : "d");
        }
        if (hour > 0) {
            sb.append(hour).append(china ? "小时" : "h");
        }
        if (minute > 0) {
            sb.append(minute).append(china ? "分钟" : "'");
        }
        if (second > 0) {
            sb.append(second).append(china ? "秒" : "″");
        }
        return sb.toString();
    }

    /**
     * 获取完整时间
     * @return full time
     */
    public String getFullTime() {
        return SimpleDateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date());
    }

    /**
     * 获取当前时间
     * @return whole time
     */
    public String getWholeTime() {
        return SimpleDateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT).format(new Date());
    }

    /**
     * 获取完整时间
	 * @param date date
	 * @return whole time
	 */
	public String getWholeTime(Date date) {
        return SimpleDateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT).format(date);
	}
	/**
     * 获取完整时间 yyyy年mm月dd日hh时mm分
	 * @param date date
	 * @return string
	 */
	public String getWholeTime(long date) {
		return getWholeTime(new Date(date));
	}

	/**
     * 将long型时间长度数据转化为文字形式时间长度
	 * 去掉了1970年1月1日8时的初始值
	 * @param duration duration
	 * @return smart time
	 */
	public String getSmartTime(long duration) {

		int[] smartDetail =  getWholeDetail(duration);

		String smartTime = "";

		if (smartDetail[5] > 0) {
			smartTime = smartDetail[5] + "秒" + smartTime;
		}
		if (smartDetail[4] > 0) {
			smartTime = smartDetail[4] + "分" + smartTime;
		}
		if (smartDetail[3] > 8) {
			smartTime = smartDetail[3] + "时" + smartDetail[4] + "分";
		}
		if (smartDetail[2] > 1) {
			smartTime = smartDetail[2] + "天" + smartDetail[3] + "时";
		}
		if (smartDetail[1] > 1) {
			smartTime = smartDetail[1] + "月" + smartDetail[2] + "天";
		}
		if (smartDetail[0] > 1970) {
			smartTime = smartDetail[0] + "年" + smartTime;
		}

		return smartTime;
	}

	public String getSmartDate(Date date) {
		return date == null ? "" : getSmartDate(date.getTime());
	}

	/**
     * 智能时间显示，12:30,昨天，前天...
	 * @param date date
	 * @return smart date
	 */
	public String getSmartDate(long date) {

		int[] nowDetails = getWholeDetail(System.currentTimeMillis());
		int[] smartDetail = getWholeDetail(date);

		String smartDate;

		if (nowDetails[0] == smartDetail[0]) {//this year
			if(nowDetails[1] == smartDetail[1]) {//this month
				String time = " " + new SimpleDateFormat("HH:mm", Locale.getDefault()).format(date);
				
				long day = nowDetails[2] - smartDetail[2];//between/(24*3600);
				if (day >= 3) {//fomer day
					smartDate = smartDetail[2] + "日" + time;
				} else if (day >= 2) {//fomer day
					smartDate = "前天" + time;
				} else if (day >= 1) {//fomer day
					smartDate = "昨天" + time;
				} else if(day >= 0) {//today
					if (0 == (nowDetails[HOUR_OF_DAY] - smartDetail[HOUR_OF_DAY])) {
						long minute = nowDetails[MINUTE] - smartDetail[MINUTE];
						if (minute < 1) {
							smartDate = "刚刚";
						} else if (minute < 31) {
							smartDate = minute + "分钟前";
						} else {
							smartDate = time;
						}
					} else {
						smartDate = time;
					}
				} else if(day >= -1) {//tomorrow
					smartDate = "明天" + time;
				} else if(day >= -2) {//the day after tomorrow
					smartDate = "后天" + time;
				} else {
					smartDate = smartDetail[2] + "日" + time;
				}
			} else {//!!!
				smartDate = smartDetail[1] + "月" + smartDetail[2] + "日";
			}
		} else {//!!!
			smartDate = smartDetail[0] + "年" + smartDetail[1] + "月";
		}
		return smartDate;
	}

	/**
     * 获取日期 年，月， 日 对应值
	 * @param date date
	 * @return int[]
	 */
	public int[] getDateDetail(Date date) {
		return date == null ? null : getDateDetail(date.getTime());
	}
	/**
     * 获取日期 年，月， 日 对应值
	 * @param time time
	 * @return int[]
	 */
	public int[] getDateDetail(long time) {
		final Calendar mCalendar = Calendar.getInstance();
		mCalendar.setTimeInMillis(time);
		return new int[]{
				mCalendar.get(Calendar.YEAR),//0
				mCalendar.get(Calendar.MONTH) + 1,//1
				mCalendar.get(Calendar.DAY_OF_MONTH),//2
		};
	}
	/**
     * 获取日期  时， 分， 秒 对应值
	 * @param time time
	 * @return int[]
	 */
	public int[] getTimeDetail(long time) {
		final Calendar mCalendar = Calendar.getInstance();
		mCalendar.setTimeInMillis(time);
		return new int[]{
				mCalendar.get(Calendar.HOUR_OF_DAY),//3
				mCalendar.get(Calendar.MINUTE),//4
				mCalendar.get(Calendar.SECOND)//5
		};
	}
	/**
     * 获取日期 年，月， 日， 时， 分， 秒 对应值
	 * @param time time
	 * @return int[]
	 */
	public int[] getWholeDetail(long time) {
		final Calendar mCalendar = Calendar.getInstance();
		mCalendar.setTimeInMillis(time);
		return new int[]{
				mCalendar.get(Calendar.YEAR),//0
				mCalendar.get(Calendar.MONTH) + 1,//1
				mCalendar.get(Calendar.DAY_OF_MONTH),//2
				mCalendar.get(Calendar.HOUR_OF_DAY),//3
				mCalendar.get(Calendar.MINUTE),//4
				mCalendar.get(Calendar.SECOND)//5
		};
	}

	/**
     * 获取两个时间的时间间隔
	 * @param sdf SimpleDateFormat
	 * @param dateLong0 date0
	 * @param dateLong1 date1
	 * @return interval(单位：秒)
	 */
	public long getBetween(SimpleDateFormat sdf, long dateLong0, long dateLong1) {
		if (sdf == null) {
			sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.getDefault());
		}
		Date date0;
		Date date1;
		long between = 0;
		try {

			date0 = sdf.parse(sdf.format(new Date(dateLong0)));
			date1 = sdf.parse(sdf.format(new Date(dateLong1)));
            assert date0 != null;
            assert date1 != null;
            between = (date0.getTime() - date1.getTime())/1000;//除以1000是为了转换成秒
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return between;
	}


	/**
     * 星座
	 * @param date date
	 * @return constellation
	 */
	public String getHoroscope(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		int month = c.get(Calendar.MONTH);				// 月份从0 ~ 11
		int dayOfMonth = c.get(Calendar.DAY_OF_MONTH);
		int[] DayArr = {19, 18, 20, 19, 20, 21, 22, 22, 22, 23, 22, 21};
		String[] starArr = {"魔羯座","水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座", "天蝎座", "射手座" };
		if (dayOfMonth > DayArr[month]) {
			month = month + 1;
			if (month == 12) {
				month = 0;
			}
		}
		return starArr[month];
	}


	/**
     * 获取智能生日
	 * @param birthday birthday time
	 * @param needYear year show?
	 * @return smart string
	 */
	public String getSmartBirthday(long birthday, boolean needYear) {
		int[] birthdayDetails = getDateDetail(birthday);
		int[] nowDetails = getDateDetail(System.currentTimeMillis());

		Calendar birthdayCalendar = Calendar.getInstance();
		birthdayCalendar.set(birthdayDetails[0], birthdayDetails[1], birthdayDetails[2]);

		Calendar nowCalendar = Calendar.getInstance();
		nowCalendar.set(nowDetails[0], nowDetails[1], nowDetails[2]);

		int days = birthdayCalendar.get(Calendar.DAY_OF_YEAR) - nowCalendar.get(Calendar.DAY_OF_YEAR);
		if (days < 8) {
			if (days >= 3) {
				return days + "天后";
			}
			if (days >= 2) {
				return Day.NAME_THE_DAY_AFTER_TOMORROW;
			}
			if (days >= 1) {
				return Day.NAME_TOMORROW;
			}
			if (days >= 0) {
				return Day.NAME_TODAY;
			}
		}

		if (needYear) {
			return birthdayDetails[0] + "年" + birthdayDetails[1] + "月" + birthdayDetails[2] + "日";
		} 
		return birthdayDetails[1] + "月" + birthdayDetails[2] + "日";
	}

	private boolean fomerIsEqualOrBigger(int[] fomer, int[] current) {
		return fomer == current || fomerIsBigger(fomer, current);
	}

    private boolean fomerIsBigger(int[] fomer, int[] current) {
		if (fomer == null || current == null) {
			return false;
		}
		int compareLength = Math.min(fomer.length, current.length);

		for (int i = 0; i < compareLength; i++) {
			if (fomer[i] < current[i]) {
				return false;
			}
			if (fomer[i] > current[i]) {
				return true;
			}
		}

		return false;
	}

	/**
     * 判断现在是否属于一段时间,不包含端点
	 * @param start start time
	 * @param end end time
	 * @return true or false
	 */
	public boolean isNowInTimeArea(int[] start, int[] end) {
		return isInTimeArea(getTimeDetail(System.currentTimeMillis()), start, end);
	}
	/**
     * 判断一个时间是否属于一段时间,不包含端点
	 * (start, end)可跨越0:00,即start < end也行
	 * @param time your time
	 * @param start start time
	 * @param end end time
	 * @return true or false
	 */
	public boolean isInTimeArea(int[] time, int[] start, int[] end) {
		if (fomerIsEqualOrBigger(end, start)) {
			return fomerIsEqualOrBigger(time, start) && fomerIsEqualOrBigger(end, time);
		}

		if (fomerIsEqualOrBigger(time, start) && fomerIsEqualOrBigger(MAX_TIME_DETAILS, time)) {
			return true;
		}
        return fomerIsEqualOrBigger(time, MIN_TIME_DETAILS) && fomerIsEqualOrBigger(end, time);
    }

}
